#include"tcp.h"
#include"Threadpool.h"
#include<vector>
#include<list>
#include<sys/epoll.h>
#include<signal.h>
#include<unistd.h>
#include<fcntl.h>
#include<map>
#include<algorithm>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/sendfile.h>

#include"MassageLog.h"
#include"UtilParseString.h"

//since Linux2.6.8 ignore
#define EPOLLMAXSIZE 100

#define MATHONSEQ " "
#define HEADSQE ": "
#define WWWROOT "../wwwroot"
#define NotFountPage "../wwwroot/NotFound.html"


class TcpServer
{
public:
    TcpServer(const std::string& Ip,uint16_t Port){
        socket._socket();
        int opt=1;
        signal(SIGPIPE,SIG_IGN);
        setsockopt(socket.Fd(),SOL_SOCKET,SO_REUSEADDR,(const void*)&opt,sizeof(opt));
        socket.Bind(Ip,Port);
        socket.Listen();
        flag=fcntl(socket.Fd(),F_GETFL,0);
        int ret=fcntl(socket.Fd(),F_SETFL,flag|O_NONBLOCK);
        if(flag==-1){
            MassageLog(ERROR,"fcntl error",strerror(errno),__FILE__,__LINE__);
        }
    }
    int Accept(sockaddr* backAddr,socklen_t& len){
        return socket.Accept(backAddr,len);
    }
    ssize_t Recv(std::string& recvMassage){
        return socket.Recv(recvMassage);
    }
    ssize_t Send(const std::string& sendMassage){
        return socket.Send(sendMassage);
    }
    void Close(){
        socket.Close();
    }
    int FD(){
        return socket.Fd();
    }
protected:
    Socket socket;
    int flag;
};

class RecvSendMassage:public TaskContext
{
public:
    RecvSendMassage(int _fd,sockaddr_in _addr):socket(_fd),addr(_addr)
    {
        Ip=std::string(inet_ntoa(addr.sin_addr));
        Port=ntohs(addr.sin_port);
    }
    void Run() override{
        while (true)
        {
            std::string Massage;
            ssize_t sizeMassage=socket.Recv(Massage);
            if(sizeMassage<=0){
                break;
            }
            std::cout<<"线程号:"<<std::this_thread::get_id()<<"|文件描述符:"<<socket.Fd()<<"|IP:port"<<Ip<<":"<<Port<<"|发送消息#"<<Massage<<std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
        std::cout<<"线程号:"<<std::this_thread::get_id()<<"|文件描述符:"<<socket.Fd()<<"|IP:port"<<Ip<<":"<<Port<<"|断开连接"<<std::endl;
        socket.Close();
    }
    void Close(){
       socket.Close();
    }
protected:
    Socket socket;
    sockaddr_in addr;
    std::string Ip;
    int Port;

};


class RegisterCGI
{
public:
    static RegisterCGI* Instence(){
        if(Is==nullptr){
            Is=new RegisterCGI();
        }
        return Is;
    }
    static void Release(){
        delete Is;
    }
    std::pair<bool,std::string> FindCGI(std::string& s){
        std::string path;
        for(auto& a: executepath){
            if(a.first==s){
                path=a.second;
                return std::pair(true,path);
            }
        }
        return std::pair(false,"");
    }
protected:
    RegisterCGI(){
        executepath.insert(std::pair("process",std::string(WWWROOT)+"/process"));
        //...
    }
    static RegisterCGI* Is;
    std::map<std::string,std::string> executepath;
};
RegisterCGI* RegisterCGI::Is=nullptr;




class FdContext{
public:
    enum Progress{
        Mathod,
        Head,
        Body,
        Body_In
    };
    FdContext(){

    }
    FdContext(int fd,sockaddr_in _addr):fd(fd),addr(_addr)
    {

    };
    FdContext(const FdContext& other){
        fd=other.fd;
        flag=other.flag;
        addr=other.addr;
        context=other.context;
        pp=other.pp;
        MathodContext=other.MathodContext;
        HeadContext=other.HeadContext;
        BodyContext=other.BodyContext;
        BodyPartLen=other.BodyPartLen;
    };
    // FdContext(FdContext&& other){
    //     fd=std::move(other.fd);
    //     flag=std::move(other.flag);
    //     addr=std::move(other.addr);
    //     context=std::move(other.context);
    //     pp=std::move(other.pp);
    //     MathodContext=std::move(other.MathodContext);
    //     HeadContext=std::move(other.HeadContext);
    //     BodyContext=std::move(other.BodyContext);
    //     BodyPartLen=std::move(other.BodyPartLen);
    // }
    //FdContext(FdContext&& other)=default;
    void setflag(int _flag){
        flag=_flag;
    };
    void Print(){
        for (int i = 0; i < MathodContext.size(); i++)
        {
            std::cout<<MathodContext[i]<<"#";
        }
        std::cout<<"\n";
        for(auto& a:HeadContext){
            std::cout<<a.first<<":"<<a.second<<"\n";
        }
        std::cout<<BodyContext<<"\n";
    }
    void ClearContext(){
        MathodContext.clear();
        HeadContext.clear();
        BodyContext.clear();
        BodyPartLen=0;
        CGI=false;
        CGICompletion=false;
        CGIExecutePath.clear();
        CGIExecuteName.clear();
        Parampasssuccess=false;
        if(pipefd[0]>0){
            close(pipefd[0]);
            pipefd[0]=-1;
        }
        if(pipefd[1]>0){
            close(pipefd[1]);
            pipefd[1]=-1;
        }
        CGIResponseContext.clear();
        pp=Progress::Mathod;
        CGIParma.clear();
    }
    int fd;
    int flag;
    sockaddr_in addr;
    std::string context;
    Progress pp=Progress::Mathod;
    std::vector<std::string> MathodContext;
    std::map<std::string,std::string> HeadContext;
    std::string BodyContext;
    long int BodyPartLen=0;
    bool CGI=false;
    std::string CGIExecutePath;
    std::map<std::string,std::string> CGIParma;
    std::string CGIExecuteName;
    bool Parampasssuccess=false;
    int pipefd[2];
    std::string CGIResponseContext;
    bool CGICompletion=false;
};






class EpollModel:public TaskContext
{
public:
    typedef std::map<int,FdContext>::iterator fditerator;
    enum AttentionEvent{
        READ,
        WRITE,
        READ_WRITE
    };
    EpollModel(int _Listenfd):Listenfd(_Listenfd),socket(Listenfd){}
    void Run() override{
        Init();
        while(true){
            int ret=epoll_wait(Epollfd,readyfd,EPOLLMAXSIZE,-1);
            if(ret==-1){
                MassageLog(ERROR,"epoll_wait:return -1",strerror(errno),__FILE__,__LINE__);
            }
            if(ret>0){
                MassageLog(MASSAGE,"接受报文",ret,__FILE__,__LINE__);
                Processing(ret);
            }
            else{
                std::this_thread::sleep_for(std::chrono::milliseconds(500));
            }
            if(_Exit){
                Release();
                break;
            }
        }
    }
    void Release(){
        close(Epollfd);
        for(auto& a: FdContextSet){
            close(a.first);
        }
    }
    void Processing(int number){
        for (int i = 0; i < number; i++)
        {
            if(readyfd[i].data.fd==Listenfd){
                AcceptNewFd();
            }
            else{
                ProcessingMassage(readyfd[i].data.fd);
            }
        }
        
    }
    void AcceptNewFd(){
        while (true)
        {
            sockaddr_in addr;
            socklen_t len;
            int fd=socket.Accept((sockaddr*)&addr,len);
            if(fd<0){
                if(errno==EWOULDBLOCK || errno == EAGAIN){
                    break;
                }
                else{
                    MassageLog(ERROR,"读取Listen套接字失败",strerror(errno),__FILE__,__LINE__);
                    exit(0);
                }
            }
            //设置非阻塞
            int flag=fcntl(fd,F_GETFL,0);
            int ret=fcntl(fd,F_SETFL,flag|O_NONBLOCK);
            if(ret==-1){
                MassageLog(ERROR,"fcntl error",strerror(errno),__FILE__,__LINE__);
            }
            FdContext temprorary(fd,addr);
            temprorary.setflag(flag);
            //std::make_pair
            //std::pair<int,FdContext> other(fd,temprorary);
            FdContextSet.insert(std::pair<int,FdContext>(fd,temprorary));
            InsertEpollEvent(fd);
        }
        
    }
    void ProcessingMassage(int fd){
        MassageLog(MASSAGE,"接收消息","文件描述符:",fd,__FILE__,__LINE__);
       while (true)
       {
            char buf[4096];
            int ret=recv(fd,buf,sizeof(buf)-1,0);
            if(ret<0){
                if(errno==EWOULDBLOCK || errno == EAGAIN){
                }
                else{
                    std::this_thread::sleep_for(std::chrono::milliseconds(5000));
                    MassageLog(ERROR,"读取字节流失败","文件描述符:",fd,strerror(errno),__FILE__,__LINE__);
                    ProcessingClose(fd);
                    return;
                    //perror("读取字节流失败！");
                }
                break;
            }
            else if(ret==0){
                //对端关闭
                MassageLog(MASSAGE,"对端关闭",fd,__FILE__,__LINE__);
                ProcessingClose(fd);
                return;
                break;
            }
            else{
                buf[ret]=0;
                FdContextSet[fd].context+=buf;
            }
       }
       MassageLog(MASSAGE,"接收完毕","文件描述符:",fd,__FILE__,__LINE__);
       //std::cout<<FdContextSet[fd].context<<"\n";
        ParseRequest(fd);
       
    }
    void ParseRequest(int fd){
        fditerator it=FdContextSet.find(fd);
        if(it==FdContextSet.end()){
            MassageLog(ERROR,"不在文件描述符不在容器内","文件描述符:",fd,__FILE__,__LINE__);
        }
        if(it->second.pp==FdContext::Progress::Mathod){
            auto& t=it->second;
            auto seq=Findseq(t);
            
            if(seq.first=="-1"){
                return;
            }
            else{
                std::string mathod=t.context.substr(0,seq.second);
                t.context.erase(0,mathod.size()+seq.first.size());
                ParseStringUtil::SplitLine(mathod,MATHONSEQ,t.MathodContext);
                t.pp=FdContext::Progress::Head;
            }
        }
        MassageLog(DEBUG,"解析请求行完成","文件描述符:",fd,__FILE__,__LINE__);
        if(it->second.pp==FdContext::Progress::Head){
            while (true)
            {
                auto& t=it->second;
                auto seq=Findseq(t);
                if(seq.first=="-1"){
                    return;
                }
                else if(seq.second==0){
                    t.context.erase(0,seq.first.size());
                    t.pp=FdContext::Progress::Body;
                    break;
                }
                else{
                    std::string mathod=t.context.substr(0,seq.second);
                    t.context.erase(0,mathod.size()+seq.first.size());
                    ParseStringUtil::SplitHeadLine(mathod,HEADSQE,t.HeadContext);
                    //t.pp=FdContext::Progress::Head;
                }
            }
            
        }
        MassageLog(DEBUG,"解析报头完成","文件描述符:",fd,__FILE__,__LINE__);
        // {
        //     auto& t=it->second;
        //     std::cout<<t.MathodContext.size()<<"\n";
        //     for (int i = 0; i < t.MathodContext.size(); i++)
        //     {
        //         std::cout<<t.MathodContext[i]<<"#";
        //     }
        //     std::cout<<"\n";
        // }
        if(it->second.pp==FdContext::Progress::Body||it->second.pp==FdContext::Progress::Body_In){
            auto& t=it->second;
            std::transform(t.MathodContext[0].begin(),t.MathodContext[0].end(),t.MathodContext[0].begin(),::towupper);
            std::map<std::string,std::string>::iterator mit=t.HeadContext.find("content-length");
            if(mit!=t.HeadContext.end()){
                if(t.context.size()<atoi(mit->second.c_str())){
                    return;
                }
                else{
                    t.BodyContext=t.context.substr(0,atoi(mit->second.c_str()));
                    t.context.erase(0,atoi(mit->second.c_str()));
                    t.pp=FdContext::Progress::Mathod;
                }
            }
            else if(t.MathodContext[0]=="GET"){
                //此时无正文
                t.pp=FdContext::Progress::Mathod;
            }
            else{
                
                MassageLog(WARING,"报文中无GET和content-Length",__FILE__,__LINE__);
                // Transfer-Encoding:chunked
                // while (true)
                // {
                //     auto seq=Findseq(t);
                //     if(seq.first=="-1"){
                //         return;
                //     }
                //     else if(seq.second==0){
                //         t.context.erase(0,seq.first.size());
                //         t.pp=FdContext::Progress::Mathod;
                //         break;
                //     }
                //     else{
                //         if(t.pp==FdContext::Progress::Body_In){

                //         }
                //         else{
                //             char* end;
                //             std::string temproary=t.context.substr(0,atoi(mit->second.c_str()));
                //             long int len=strtol(temproary.c_str(),&end,16);
                //             t.context.erase(0,atoi(mit->second.c_str()));
                //             t.pp=FdContext::Progress::Body_In;
                //             t.BodyPartLen=len;
                //         }
                //     }
                // }
                
            }
        }
        auto& t=it->second;
        //解析出一个完整的报文
        MassageLog(MASSAGE,"解析出完整报文",fd,__FILE__,__LINE__);
        t.Print();
        
        bool useable=true;
        if(t.MathodContext.size()!=3){
            MassageLog(WARING,"状态行不合法！",__FILE__,__LINE__);
            useable=false;
        }
        if(useable){
            ParseResource(t);
            BuildResponse(fd);
        }
        else{
            BuildNotFoundPage(fd);
        }
        ClearfdContext(fd);
    }
    void ParseResource(FdContext& t){
         if(t.MathodContext[1]=="/"){
            t.MathodContext[1]=std::string(WWWROOT)+"/index.html";
        }
        else{
            size_t pos=t.MathodContext[1].find("?",0);
            if(pos!=std::string::npos){
                size_t bpos=t.MathodContext[1].rfind("/",pos);
                if(bpos!=std::string::npos){
                    std::string cginame=t.MathodContext[1].substr(bpos+1,pos-bpos-1);
                    auto a=RegisterCGI::Instence()->FindCGI(cginame);
                    if(a.first){
                        t.CGIExecutePath=a.second;
                        t.CGIExecuteName=cginame;
                        t.CGI=true;
                        std::string param=t.MathodContext[1].substr(pos+1,t.MathodContext.size()-pos-1);
                        ParseCGIParam(t,param);
                        return;
                    }
                    else{
                        //当作普通路径处理
                    }
                    //t.MathodContext[1]=std::string(WWWROOT)+t.MathodContext[1].substr(0,bpos+1);
                }
                else{//当作普通路径处理
                }
            }
            else{
                if(t.MathodContext[0]=="POST"){
                    size_t bpos=t.MathodContext[1].rfind("/",t.MathodContext[1].size());
                    if(bpos!=std::string::npos){
                        std::string cginame=t.MathodContext[1].substr(bpos+1,t.MathodContext[1].size()-bpos-1);
                        auto a=RegisterCGI::Instence()->FindCGI(cginame);
                        if(a.first){
                            t.CGIExecutePath=a.second;
                            t.CGIExecuteName=cginame;
                            t.CGI=true;
                            //std::string param=t.MathodContext[1].substr(pos+1,t.MathodContext.size()-pos-1);
                            ParseCGIParam(t,t.BodyContext);
                            return;
                        }
                        else{

                        }
                    }
                    else{
                        //当作普通路径处理
                    }
                }
                else{
                    //当作普通路径处理
                }
            }
            t.MathodContext[1]=std::string(WWWROOT)+t.MathodContext[1];
        }
        //std::cout<<t.MathodContext[1]<<"\n";
    }
    void ParseCGIParam(FdContext& t,std::string& Param){
        std::vector<std::string> v;
        std::string s=Param;

        while (true)
        {
            size_t pos = s.find("&");
            if(pos!=std::string::npos){
                std::string subs=s.substr(0,pos);
                ParseStringUtil::SplitLine(subs,"=",v);
                s=s.erase(0,subs.size()+1);
            }
            else{
                break;
            }
        }
         size_t pos = s.find("=");
         if(pos!=std::string::npos){
            ParseStringUtil::SplitLine(s,"=",v);
        }
        if(v.size()%2!=0||v.size()==0){
            t.CGICompletion=false;
            return;
        }

        for (int i = 0; i < v.size()/2; i++)
        {
            t.CGIParma.insert(std::pair(v[i*2],v[i*2+1]));
        }
        t.CGICompletion=true;  
    }
    void ClearfdContext(int fd){
        fditerator it=FdContextSet.find(fd);
        if(it!=FdContextSet.end()){
            auto& t=it->second;
            t.ClearContext();
        }
        else{

        }
    }
    void BuildNotFoundPage(int fd,bool sendhead=false){
        fditerator it=FdContextSet.find(fd);
        if(it==FdContextSet.end()){
            //
        }
        auto& t=it->second;
        struct stat filedescribe;
        int ret=stat(NotFountPage,&filedescribe);
        if(ret==-1){
            MassageLog(WARING,"打开失败",strerror(errno),__FILE__,__LINE__);
            return;
        }
        int sendfd=open(NotFountPage,O_RDONLY);
        if(sendfd==-1){
            MassageLog(WARING,"打开失败",strerror(errno),__FILE__,__LINE__);
            return;
        }
        if(!sendhead){
            
        }
        else{
            std::string reseponse;
            reseponse+="HTTP/1.1 ";
            reseponse+="404 ";
            reseponse+="Not Found\r\n";
            reseponse+="Content-Length: ";
            reseponse+=std::to_string(filedescribe.st_size);
            reseponse+="\r\n";
            reseponse+="content-type: ";
            reseponse+="text/html";
            reseponse+="\r\n";
            reseponse+="\r\n";
            bool success=SendResponse(fd,reseponse);
            if(!success){
                return;
            }
        }

        int total=filedescribe.st_size;
        while (true)
        {
            ret=sendfile(fd,sendfd,NULL,filedescribe.st_size);
            if(ret==-1){
                MassageLog(WARING,"发送文件失败",__FILE__,__LINE__);
                close(sendfd);
                return;
            }
            total-=ret;
            if(total==0){
                break;
            }
        }
        MassageLog(MASSAGE,"NotFound发送完毕",fd,"发送了字节数",filedescribe.st_size,__FILE__,__LINE__);
        close(sendfd); 
    }
    void BuildCGIResponse(FdContext& t){
        //1. 创建管道
        //M:父进程，C子进程
        //0 读   1 写
        int PtoC[2];
        int CtoP[2];
        int ret=pipe(PtoC);
        if(ret==-1){
            return;
        }
        ret=pipe(CtoP);
        if(ret==-1){
            close(PtoC[0]);
            close(PtoC[1]);
            return;
        }
        pid_t id=fork();
        if(id==0){
            //子进程
            //设置环境变量或通过管道传参
            close(PtoC[1]);
            close(CtoP[0]);
            //子进程从标准输入中读
            int ret=dup2(PtoC[0],0);
            if(ret==-1){
                exit(2);
            }
            //子进程往标准输出中写
            ret=dup2(CtoP[1],1);
            if(ret==-1){
                exit(2);
            }
            if(t.MathodContext[0]=="POST"){
                //通过管道传参,子进程中处理

            }
            else{
                //通过环境变量传参
                for (auto& a:t.CGIParma)
                {
                    int ret=setenv(a.first.c_str(),a.second.c_str(),1);
                    if(ret==-1){

                    }
                }
            }
            //进程替换
            std::string f="./"+t.CGIExecuteName;
            execl(t.CGIExecutePath.c_str(),f.c_str(),NULL);
        }
        close(PtoC[0]);
        close(CtoP[1]);
        t.pipefd[0]=PtoC[1];
        t.pipefd[1]=CtoP[0];

        if(!t.Parampasssuccess){
            if(t.MathodContext[0]=="POST"){
                //管道传参
                for (auto& a:t.CGIParma)
                {
                    std::string buf=a.first+a.second;
                    int total=buf.size();
                    while (true)
                    {
                        int ret=write(PtoC[1],buf.c_str()+(buf.size()-total),buf.size());
                        total-=ret;
                        if(total==0){
                            break;
                        }
                        else if(ret<0){
                            //对端关闭
                            return;
                        }
                        else{
                            
                        }
                    }
                }
                t.Parampasssuccess=true;
            }
            else{

            }
        }
        
        int flag=fcntl(CtoP[0],F_GETFL,0);
        int ret=fcntl(CtoP[0],F_SETFL,flag|O_NONBLOCK);
        if(ret==-1){
            MassageLog(WARING,"设置从子进程读管道文件描述符非阻塞失败",strerror(errno),__FILE__,__LINE__);
        }

        //已经通过管道传输了结果或通过环境变量传递了参数,等待结果
        while (true)
        {
            char buf[4096];
            int ret=read(CtoP[0],buf,sizeof(buf)-1);
            if(ret>0){
                buf[ret]=0;
                t.CGIResponseContext+=buf;
            }
            else if(ret==0){
                //对端关闭
                break;
            }
            else if(ret<0){
                if(errno==EWOULDBLOCK||errno==EAGAIN){
                    continue;
                }
                else{
                    return;
                }
            }
            else{
                //???
                return;
            }
        }

        std::string reseponse;
        reseponse+="HTTP/1.1 ";
        reseponse+="200 ";
        reseponse+="OK\r\n";
        reseponse+="Content-Length: ";
        reseponse+=std::to_string(t.CGIResponseContext.size());
        reseponse+="\r\n";
        reseponse+="content-type: ";
        reseponse+="text/html";
        reseponse+="\r\n";
        reseponse+="\r\n";
        bool success=SendResponse(t.fd,reseponse);
        if(!success){
            MassageLog(ERROR,"发送报文出错",t.fd,__FILE__,__LINE__);
            return;
        }
        bool success=SendResponse(t.fd,t.CGIResponseContext);
        if(!success){
            MassageLog(ERROR,"发送报文出错",t.fd,__FILE__,__LINE__);
            return;
        }
        MassageLog(MASSAGE,"CGI过程完成!",t.fd,__FILE__,__LINE__);
    }
    void BuildResponse(int fd){
        fditerator it=FdContextSet.find(fd);
        if(it==FdContextSet.end()){
            //
        }
        auto& t=it->second;
        if(t.CGICompletion){
            BuildCGIResponse(t);
            return;
        }
        struct stat filedescribe;
        int ret=stat(t.MathodContext[1].c_str(),&filedescribe);
        if(ret==-1){
            MassageLog(WARING,"打开失败",strerror(errno),__FILE__,__LINE__);
            BuildNotFoundPage(fd,true);
            return;
        }
        int sendfd=open(t.MathodContext[1].c_str(),O_RDONLY);
        if(sendfd==-1){
            MassageLog(WARING,"打开失败",strerror(errno),__FILE__,__LINE__);
            BuildNotFoundPage(fd,true);
            return;
        }
        std::string reseponse;
        reseponse+="HTTP/1.1 ";
        reseponse+="200 ";
        reseponse+="OK\r\n";
        reseponse+="Content-Length: ";
        reseponse+=std::to_string(filedescribe.st_size);
        reseponse+="\r\n";
        reseponse+="content-type: ";
        reseponse+="text/html";
        reseponse+="\r\n";
        reseponse+="\r\n";
        bool success=SendResponse(fd,reseponse);
        if(!success){
            MassageLog(ERROR,"发送报文出错",fd,__FILE__,__LINE__);
            return;
        }
        int total=filedescribe.st_size;
        while (true)
        {
            ret=sendfile(fd,sendfd,NULL,filedescribe.st_size);
            if(ret==-1){
                MassageLog(WARING,"发送文件失败",__FILE__,__LINE__);
                BuildNotFoundPage(fd);
                close(sendfd);
                return;
            }
            total-=ret;
            if(total==0){
                break;
            }
        }
         MassageLog(MASSAGE,"资源发送完毕",fd,"发送了字节数",filedescribe.st_size,__FILE__,__LINE__);
        close(sendfd);
    }
    bool SendResponse(int fd,std::string& reseponse){
        int total=reseponse.size();
        bool success=true;
        while (true)
        {
            int ret=send(fd,reseponse.c_str(),reseponse.size(),0);
            if(ret<0){
                if(errno==EWOULDBLOCK || errno == EAGAIN){
                    continue;
                }
                else if(errno==EPIPE){
                    //对端关闭
                    ProcessingClose(fd);
                    MassageLog(MASSAGE,"对端关闭",__FILE__,__LINE__);
                    success=false;
                    break;
                }
                else{
                    //
                    ProcessingClose(fd);
                    MassageLog(WARING,"发送时出现未知错误",__FILE__,__LINE__);
                    success=false;
                    break;
                }
            }
            else if(ret==0){
                //对端关闭
                ProcessingClose(fd);
                return false;
            }
            total-=ret;
            if(total==0){
                break;
            }
            else{

            }
        }
        MassageLog(MASSAGE,"发送数据完毕",fd,__FILE__,__LINE__);
        return success;
    }
    std::pair<std::string,size_t> Findseq(FdContext& c){
        size_t pos=c.context.find("\r\n",0);
        if(pos!=std::string::npos){
            return std::pair<std::string,size_t>(std::string("\r\n"),pos);
        }
        pos=c.context.find("\n",0);
        if(pos!=std::string::npos){
            return std::pair<std::string,size_t>(std::string("\n"),pos);
        }
        else{
            
        }
        return std::pair<std::string,size_t>(std::string("-1"),0);
    }
    void ProcessingClose(int fd){
        MassageLog(MASSAGE,"关闭文件描述符",fd,__FILE__,__LINE__);
        std::map<int,FdContext>::iterator it=FdContextSet.find(fd);
        if(it!=FdContextSet.end()){
            //epoll_event event;
            epoll_ctl(Epollfd,EPOLL_CTL_DEL,it->first,NULL);
            close(fd);
            FdContextSet.erase(it);
        }
        else{
            //不会运行到这;
        }
    }
    void ParseLine(){

    }
    void Init(){
        Epollfd=epoll_create(EPOLLMAXSIZE);
        if(Epollfd==-1){
            MassageLog(ERROR,"创建epoll失败",__FILE__,__LINE__);
        }
        InsertEpollEvent(Listenfd);
    }
    void InsertEpollEvent(int fd,AttentionEvent eventtype=AttentionEvent::READ){
        epoll_event event;
        if(ET){
            event.events=EPOLLIN | EPOLLET;
        }
        else{
            event.events=EPOLLIN;
        }
        event.data.fd=fd;
        int ret=epoll_ctl(Epollfd,EPOLL_CTL_ADD,fd,&event);
        if(ret==-1){
            MassageLog(ERROR,"添加epoll失败",__FILE__,__LINE__);
        }
    }
    void Exit(){
        _Exit=true;
    }
protected:
    int Listenfd;
    int Epollfd=-1;
    std::map<int,FdContext> FdContextSet;
    epoll_event readyfd[EPOLLMAXSIZE];
    bool _Exit=false;
    int ET=0;
    Socket socket;
};


int main(int argc,char* argv[]){
    if(argc!=3){
        cout<<"参数不为3,格式:program Ip Port"<<endl;
        return 0;
    }

    //自动回收子进程
    signal(SIGCHLD,SIG_IGN);
    TcpServer server(std::string(argv[1]),atoi(argv[2]));
    Threatpool threadpool(5);
    std::string s;
    EpollModel epollmodel(server.FD());
    threadpool.pushTask(&epollmodel);
    while (true)
    {
        std::cin>>s;
        if(s==std::string("exit")){
            break;
        }
        s.clear();
        // sockaddr_in addr;
        // socklen_t len;
        // int fd=server.Accept((sockaddr*)&addr,len);
        // fdArray.emplace_back(RecvSendMassage(fd,addr));
        // threadpool.pushTask(&fdArray.back());
    }
    epollmodel.Exit();
    threadpool.Close();
    server.Close();
    RegisterCGI::Release();
    return 0;
}